﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

using LowLevelGraphics.Drawing;

namespace LowLevelGraphics.Filter
{
    //TODO: implement for different cases. At the moment just a floodfill is used to accomplish this task 

    public enum BORDERSIDE
    {
        TOP,
        LEFT,
        BOTTOM,
        RIGHT
    }

    /// <summary>
    /// imclearborder suppresses structures that are lighter than 
    /// their surroundings and that are connected to the image border. 
    /// (In other words, use this function to clear the image border.) 
    /// IM can be a grayscale or binary image. The output image, IM2, 
    /// is grayscale or binary, respectively. 
    /// The default connectivity is 8 for two dimensions, 
    /// 26 for three dimensions, and conndef(ndims(BW),'maximal') 
    /// for higher dimensions.
    /// </summary>
    /// <remarks>For grayscale images, imclearborder tends to reduce
    /// the overall intensity level in addition to suppressing border structures.</remarks>
    public class ImageClearBorder : BaseForeBackgroundColorFilter
    {
        /// <summary>
        /// True = use binary mode to remove, false = use gray mode to remove
        /// </summary>
        protected bool m_bProcessBinary = true;
        protected int m_nNeighbouring = 8;
        protected BORDERSIDE M_BORDERSIDE = BORDERSIDE.LEFT | BORDERSIDE.RIGHT | BORDERSIDE.TOP | BORDERSIDE.BOTTOM;

        /// <summary>
        /// Initializes a new instance of the <see cref="ImageClearBorder"/> class.
        /// </summary>
        public ImageClearBorder()
        {
        }

        /// <summary>
        /// Initializes a new instance of the ImageClearBorder class.
        /// </summary>
        /// <param name="_imclearborder">The _imclearborder.</param>
        internal ImageClearBorder(ImageClearBorder _imclearborder)
        {
            this.m_bProcessBinary = _imclearborder.m_bProcessBinary;
            this.m_nNeighbouring = _imclearborder.m_nNeighbouring;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <value><c>true</c> if [process binary]; otherwise, <c>false</c>.</value>
        public bool ProcessBinary
        {
            get { return m_bProcessBinary; }
            set { m_bProcessBinary = value; }
        }

        /// <summary>
        /// Gets or sets the neighbouring.
        /// </summary>
        /// <value>The neighbouring.</value>
        public int Neighbouring
        {
            get { return m_nNeighbouring; }
            set { m_nNeighbouring = value; }
        }

        /// <summary>
        /// Gets or sets the border side.
        /// </summary>
        /// <value>The border side.</value>
        public BORDERSIDE BorderSide
        {
            get { return M_BORDERSIDE; }
            set { M_BORDERSIDE = value; }
        }

        /// <summary>
        /// Execute this Filter
        /// A Debug Statement is written if a concrete Filter is called
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <returns></returns>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            if (m_bProcessBinary)
            {
                BinaryModeClearing(M_BORDERSIDE, _bitmap);
            }
            else
            {
                GrayModeClearing(M_BORDERSIDE, _bitmap);
            }
            return _bitmap;
        }

        /// <summary>
        /// Binaries the mode clearing.
        /// </summary>
        /// <param name="_bitmap">The _bitmap.</param>
        private void BinaryModeClearing(BORDERSIDE _borderside, UnsafeBitmap _bitmap)
        {
            int nWidth = _bitmap.Width;
            int nHeight = _bitmap.Height;
            int x = 0;
            int y = 0;

            Color color = Color.Transparent;

            UnsafeGraphics unsafeGraphics = UnsafeGraphics.FromImage(_bitmap);

            //process upper border
            for (x = 0; x < nWidth; x++)
            {
                color = _bitmap[x, 0];
                if (color == m_ColorForeground)
                {
                    unsafeGraphics.FloodFill(new Point(x, 0), m_ColorBackground);
                }
            }

            //process lower border
            for (x = 0; x < nWidth; x++)
            {
                color = _bitmap[x, nHeight - 1];
                if (color == m_ColorForeground)
                {
                    unsafeGraphics.FloodFill(new Point(x, nHeight - 1), m_ColorBackground);
                }
            }

            //process left border
            for (y = 0; y < nHeight; y++)
            {
                color = _bitmap.GetPixel(0, y);
                if (color == m_ColorForeground)
                {
                    unsafeGraphics.FloodFill(new Point(0, y), m_ColorBackground);
                }
            }

            //process right border
            for (y = 0; y < nHeight; y++)
            {
                color = _bitmap.GetPixel(nWidth - 1, y);
                if (color == m_ColorForeground)
                {
                    unsafeGraphics.FloodFill(new Point(nWidth - 1, y), m_ColorBackground);
                }
            }

            unsafeGraphics.Dispose();
        }

        /// <summary>
        /// Grays the mode clearing.
        /// </summary>
        /// <param name="_bitmap">The _bitmap.</param>
        private void GrayModeClearing(BORDERSIDE _borderside, UnsafeBitmap _bitmap)
        {
            int nWidth = _bitmap.Width;
            int nHeight = _bitmap.Height;
            int x = 0;
            int y = 0;

            Color color = Color.Transparent;

            UnsafeGraphics unsafeGraphics = UnsafeGraphics.FromImage(_bitmap);

            //process upper border
            if ((M_BORDERSIDE & BORDERSIDE.TOP) == BORDERSIDE.TOP)
            {
                for (x = 0; x < nWidth; x++)
                {
                    color = _bitmap[x, 0];
                    if (color == m_ColorForeground)
                    {
                        unsafeGraphics.FloodFill(new Point(x, 0), m_ColorBackground);
                    }
                }
            }

            //process lower border
            if ((M_BORDERSIDE & BORDERSIDE.BOTTOM) == BORDERSIDE.BOTTOM)
            {
                for (x = 0; x < nWidth; x++)
                {
                    color = _bitmap[x, nHeight - 1];
                    if (color == m_ColorForeground)
                    {
                        unsafeGraphics.FloodFill(new Point(x, nHeight - 1), m_ColorBackground);
                    }
                }
            }

            //process left border
            if ((M_BORDERSIDE & BORDERSIDE.LEFT) == BORDERSIDE.LEFT)
            {
                for (y = 0; y < nHeight; y++)
                {
                    color = _bitmap.GetPixel(0, y);
                    if (color == m_ColorForeground)
                    {
                        unsafeGraphics.FloodFill(new Point(0, y), m_ColorBackground);
                    }
                }
            }

            //process right border
            if ((M_BORDERSIDE & BORDERSIDE.RIGHT) == BORDERSIDE.RIGHT)
            {
                for (y = 0; y < nHeight; y++)
                {
                    color = _bitmap.GetPixel(nWidth - 1, y);
                    if (color == m_ColorForeground)
                    {
                        unsafeGraphics.FloodFill(new Point(nWidth - 1, y), m_ColorBackground);
                    }
                }
            }

            unsafeGraphics.Dispose();
        }

        /// <summary>
        /// Clones this instance.
        /// </summary>
        public override object Clone()
        {
            return new ImageClearBorder(this);
        }
    }
}
